package cn.iocoder.yudao.module.wms.service.rdrecord11;

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
import cn.iocoder.yudao.module.bpm.service.task.ActHiProcinstServiceImpl;
import cn.iocoder.yudao.module.wms.controller.admin.rdrecord11.vo.Rdrecord11PageReqVO;
import cn.iocoder.yudao.module.wms.controller.admin.rdrecord11.vo.Rdrecord11SaveReqVO;
import cn.iocoder.yudao.module.wms.dal.dataobject.rdrecord11.Rdrecord11DO;
import cn.iocoder.yudao.module.wms.dal.dataobject.rdrecord11.Rdrecords11DO;
import cn.iocoder.yudao.module.wms.dal.dataobject.stock.StockDO;
import cn.iocoder.yudao.module.wms.dal.mysql.rdrecord11.Rdrecord11Mapper;
import cn.iocoder.yudao.module.wms.dal.mysql.rdrecord11.Rdrecords11Mapper;
import cn.iocoder.yudao.module.wms.dal.redis.RedisKeyConstants;
import cn.iocoder.yudao.module.wms.dal.redis.serialNumber.WmsSerialNumberRedisDAO;
import cn.iocoder.yudao.module.wms.enums.inventory.BusinessType11;
import cn.iocoder.yudao.module.wms.service.stock.StockService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.RDRECORD11_NOT_EXISTS;
import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.RDRECORDS11_SERIALNUMBER_EXISTS;

/**
 * 材料出库主 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class Rdrecord11ServiceImpl implements Rdrecord11Service {

    /**
     * OA 对应的流程定义 KEY
     */
    public static final String PROCESS_KEY = "rdrecord11-flow";
    @Resource
    private BpmProcessInstanceApi processInstanceApi;
    @Resource
    private Rdrecord11Mapper rdrecord11Mapper;
    @Resource
    private Rdrecords11Mapper rdrecords11Mapper;
    @Resource
    private ActHiProcinstServiceImpl actHiProcinstService;
    @Resource
    private WmsSerialNumberRedisDAO serialNumberRedisDAO;
    @Resource
    private StockService stockService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createRdrecord11(Rdrecord11SaveReqVO createReqVO) {
        String serialNumber = serialNumberRedisDAO.generate(WmsSerialNumberRedisDAO.RD11_SERIAL_PREFIX, RedisKeyConstants.SERIAL11);
        if (rdrecord11Mapper.selectBySerialNumber(serialNumber) != null) {
            throw exception(RDRECORDS11_SERIALNUMBER_EXISTS);
        }
        // 插入
        Rdrecord11DO rdrecord11 = BeanUtils.toBean(createReqVO, Rdrecord11DO.class,in -> in.setSerialNumber(serialNumber));
        rdrecord11Mapper.insert(rdrecord11);

        // 插入子表
        createRdrecords11List(rdrecord11.getId(), createReqVO.getRdrecords11s());
        // 返回
        return rdrecord11.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void process(Long id) {
        // 发起 BPM 流程
        Map<String, Object> processInstanceVariables = new HashMap<>();
        String processInstanceId = processInstanceApi.createProcessInstance(getLoginUserId(),
                new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY)
                        .setVariables(processInstanceVariables).setBusinessKey(String.valueOf(id)));
        // 将工作流的编号，更新到 业务表单中
        rdrecord11Mapper.updateById(new Rdrecord11DO().setId(id).setProcessInstanceId(processInstanceId).setStatus(BpmTaskStatusEnum.RUNNING.getStatus()));

        //将链接加入到ACT_HI_PROCINST表中
        actHiProcinstService.updateURLById("/inventory/rdrecord11FormInfo?id=" + id,processInstanceId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRdrecord11(Rdrecord11SaveReqVO updateReqVO) {
        // 校验存在
        validateRdrecord11Exists(updateReqVO.getId());
        // 更新
        Rdrecord11DO updateObj = BeanUtils.toBean(updateReqVO, Rdrecord11DO.class);
        rdrecord11Mapper.updateById(updateObj);

        // 更新子表
        updateRdrecords11List(updateReqVO.getId(), updateReqVO.getRdrecords11s());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRdrecord11Status(Long id, Integer status) {
        // 校验存在
        validateRdrecord11Exists(id);
        if (status.equals(BpmTaskStatusEnum.APPROVE.getStatus())) {
            //结束则更新审核人
            rdrecord11Mapper.updateById(new Rdrecord11DO().setId(id).setStatus(status).setAuditor(String.valueOf(getLoginUserId())).setAuditTime(LocalDateTime.now()));
        } else {
            rdrecord11Mapper.updateById(new Rdrecord11DO().setId(id).setStatus(status));
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteRdrecord11(Long id) {
        // 校验存在
        validateRdrecord11Exists(id);
        // 删除
        rdrecord11Mapper.deleteById(id);

        // 删除子表
        deleteRdrecords11ByOrderId(id);
    }

    private void validateRdrecord11Exists(Long id) {
        if (rdrecord11Mapper.selectById(id) == null) {
            throw exception(RDRECORD11_NOT_EXISTS);
        }
    }

    @Override
    public Rdrecord11DO getRdrecord11(Long id) {
        return rdrecord11Mapper.selectById(id);
    }

    @Override
    public Rdrecord11DO getRdrecord11ByProcessInstanceId(String processInstanceId) {
        return rdrecord11Mapper.selectByProcessInstanceId(processInstanceId);
    }

    @Override
    public PageResult<Rdrecord11DO> getRdrecord11Page(Rdrecord11PageReqVO pageReqVO) {
        return rdrecord11Mapper.selectPage(pageReqVO,getCondition(pageReqVO.getPersonId()),
                getCondition(pageReqVO.getDeptId()),getCondition(pageReqVO.getWarehouseId()),
                getCondition(pageReqVO.getCreator()), getCondition(pageReqVO.getAuditor()));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void businessProcessing(Long id, int type) {
        // 校验存在
        validateRdrecord11Exists(id);
        Rdrecord11DO rdrecord11 = rdrecord11Mapper.selectById(id);
        //获取子表信息
        List<Rdrecords11DO> rdrecords11DOList = rdrecords11Mapper.selectListByOrderId(id);
        //领料
        if (rdrecord11.getBusinessType().equals(BusinessType11.GET_MATERIALS.getBusinessType())) {
            for (Rdrecords11DO rdrecords11 : rdrecords11DOList) {
                //执行出库方法
                StockDO stockDO = new StockDO().setQty(rdrecords11.getQuantity() * type).setInventoryId(convertInteger(rdrecords11.getInventoryId()))
                        .setWarehouseId(convertInteger(rdrecord11.getWarehouseId())).setLocationId(convertInteger(rdrecords11.getLocationId()))
                        .setBatchCode(rdrecords11.getBatch());
                stockService.Outbound(stockDO);
            }
        } else if (rdrecord11.getBusinessType().equals(BusinessType11.RETURN_MATERIALS.getBusinessType())) {
            for (Rdrecords11DO rdrecords11 : rdrecords11DOList) {
                //执行入库方法
                StockDO stockDO = new StockDO().setQty(rdrecords11.getQuantity() * type).setInventoryId(convertInteger(rdrecords11.getInventoryId()))
                        .setWarehouseId(convertInteger(rdrecord11.getWarehouseId())).setLocationId(convertInteger(rdrecords11.getLocationId()))
                        .setBatchCode(rdrecords11.getBatch());
                stockService.store(stockDO);
            }
        }
    }

    // ==================== 子表（材料出库子） ====================

    @Override
    public List<Rdrecords11DO> getRdrecords11ListByOrderId(Long orderId) {
        return rdrecords11Mapper.selectListByOrderId(orderId);
    }

    private void createRdrecords11List(Long orderId, List<Rdrecords11DO> list) {
        list.forEach(o -> o.setOrderId(orderId));
        rdrecords11Mapper.insertBatch(list);
        businessProcessing(orderId,1);
    }

    private void updateRdrecords11List(Long orderId, List<Rdrecords11DO> list) {
        deleteRdrecords11ByOrderId(orderId);
        createRdrecords11List(orderId, list);
    }

    private void deleteRdrecords11ByOrderId(Long orderId) {
        businessProcessing(orderId,-1);
        rdrecords11Mapper.deleteByOrderId(orderId);
    }
    /**
     * 去空转换
     * @param ids id
     * @return id集合
     */
    private Set<String> getCondition(String[] ids) {
        if (ids == null) {
            return Collections.emptySet();
        }
        return new HashSet<>(Arrays.asList(ids));
    }

    /**
     * long转Integer
     * @param param 参数
     * @return Integer
     */
    private Integer convertInteger(Long param) {
        return Integer.valueOf(String.valueOf(param));
    }

}